﻿Imports System.Threading.Tasks
Imports System.Net.Sockets
Imports System.Net
Imports System.Threading

Public Class frmMain
    Private WithEvents ConsoleSocket As Connections
    Private noClose As Boolean = False
    Private SyncData As DataTable
    Private SyncObject As Object

    Private WaitTaskResponse As Boolean = False, WaitTaskResponseHandler As Integer = 0

    'Decalare Task
    Public SyncResponseTask As Task = Nothing, ResendOutbox As Task = Nothing, _
            ConnMonitor As Task = Nothing, LoginMonitor As Task = Nothing, _
            SyncTask As Task = Nothing

    Public tsWaitTask As CancellationTokenSource, tsSyncTask As CancellationTokenSource, _
            tsConnMonitor As CancellationTokenSource, tsResendOutbox As CancellationTokenSource, _
            tsLoginMonitor As CancellationTokenSource
    '-------------------------------

    Private Sub frmMain_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
        If noClose = False Then
            frmLoginMain.Close()
        End If
    End Sub

    Private Sub doBackToLogin()
        noClose = True
        Me.Hide()
        frmLoginMain.Show()
    End Sub

    Protected Overrides Sub SetVisibleCore(ByVal value As Boolean)
        If Not Me.IsHandleCreated Then
            Me.CreateHandle()
            value = False
        End If
        MyBase.SetVisibleCore(value)
    End Sub

    Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        If Me.Visible = True Then
            SetVisibleCore(True)
            Console_Append("Logged in as " & localNick)
            If mysql_isconnected() = False Then
                frmDBOption.ShowDialog()
            End If
            ribbonUser.Text = localNick
            noClose = False
        End If
    End Sub

    Private Sub iLogout_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles iLogout.ItemClick
        doBackToLogin()
    End Sub

    Private Sub iMessage_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles iMessage.ItemClick
        frmMessage.ShowDialog()
    End Sub

    Private Sub iDatabase_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles iDatabase.ItemClick
        frmDBOption.ShowDialog()
    End Sub

    Private Sub TmrMain_Tick(sender As Object, e As EventArgs) Handles TmrMain.Tick
        BarStaticItemDateTime.Caption = Date.Now.ToString("MMMM dd, yyyy  HH:mm:ss")
    End Sub

    Public Sub Console_Append(ByVal msg As String)
        If txtConsole.Lines.Length > 500 Then txtConsole.Text = ""

        If txtConsole.Text.Length = 0 Then
            txtConsole.AppendText("> " & msg)
        Else
            txtConsole.AppendText(msg)
        End If

        txtConsole.ScrollToCaret()
        If txtConsole.Text.Length > 0 Then
            txtConsole.AppendText(ControlChars.NewLine)
            txtConsole.AppendText("> ")
        End If
        txtConsole.Select(txtConsole.TextLength, 0)
    End Sub

    Private Sub setConnectState(ByVal code As Byte)
        Select Case code
            Case 0
                Console_Append("Disconnected")
                BarStaticItemConnection.Caption = "Disconnected"
                BarStaticItemConnection.ImageIndex = 30
                iConnect.Caption = "Connect"
                iConnect.LargeImageIndex = 10
            Case 1
                Console_Append("Connecting...")
                BarStaticItemConnection.Caption = "Connecting..."
                BarStaticItemConnection.ImageIndex = 30
                iConnect.Caption = "Disconnect"
                iConnect.LargeImageIndex = 10
            Case 2
                Console_Append("Authenticating...")
                BarStaticItemConnection.Caption = "Authenticating..."
                BarStaticItemConnection.ImageIndex = 30
                iConnect.Caption = "Disconnect"
                iConnect.LargeImageIndex = 10
            Case 3
                Console_Append("Connected to " & ip & ":" & port & " as " & nickname)
                BarStaticItemConnection.Caption = "Connected as " & nickname
                BarStaticItemConnection.ImageIndex = 29
                iConnect.Caption = "Disconnect"
                iConnect.LargeImageIndex = 21
                frmLoginMain.setNotifyBaloon("Synchronization Client", "Connected to Server as " & nickname & "!" & vbCrLf & _
                                                        "Server: " & ip & ":" & port, ToolTipIcon.Info)
            Case 4
                Console_Append("Disconnected")
                BarStaticItemConnection.Caption = "Disconnected"
                BarStaticItemConnection.ImageIndex = 30
        End Select
    End Sub

    Public Sub doLogin(ByVal user As String, ByVal pass As String)
        Try
            If ConnMonitor IsNot Nothing And tsConnMonitor IsNot Nothing Then
                If ConnMonitor.Status = TaskStatus.Running And tsConnMonitor.IsCancellationRequested = False Then
                    ConnMonitor.Wait()
                End If
            End If
        Catch ex As Exception

        End Try
        ConsoleSocket = Nothing
        SockGlobal = Nothing
        Me.Invoke(Sub() setConnectState(1))
        tsLoginMonitor = New CancellationTokenSource
        LoginMonitor = Task.Factory.StartNew(Sub() doConnect(user, pass), tsLoginMonitor.Token)
    End Sub

    Private Sub doConnect(Optional ByVal user As String = "", Optional ByVal pass As String = "")
        'Define Host IP Address
        'Dim HostEntry As IPHostEntry = Dns.GetHostEntry(ip)
        Dim ipAddr As IPAddress() = Dns.GetHostAddresses(ip) 'HostEntry.AddressList
        Dim i As Integer = 0
        Dim indexTmp As String = -1

        For i = 0 To ipAddr.Count - 1
            Select Case ipAddr(i).AddressFamily
                Case System.Net.Sockets.AddressFamily.InterNetwork
                    If indexTmp = -1 Then
                        indexTmp = i
                    End If
                    If ipAddr(i).ToString.Equals(ip) Then
                        Exit For
                    End If
            End Select
            If indexTmp > -1 And i >= ipAddr.Count - 1 Then
                i = indexTmp
                Exit For
            End If
        Next
        '--------------- End IP Check
        Do
            Try
                If tsLoginMonitor.Token.IsCancellationRequested Then Exit Sub

                If user.Length >= 4 And pass.Length >= 4 Then
                    ConsoleSocket = New Connections(ipAddr(i), port)
                    ConsoleSocket.AwaitData()
                    ConsoleSocket.Login(user, pass)
                    Me.Invoke(Sub() setConnectState(2))
                    username = user
                    password = pass
                    Exit Sub
                Else
                    Me.Invoke(New Action(Of String)(AddressOf Console_Append), "Harap Isi Username/Password Dengan benar")
                    Me.Invoke(Sub() frmLogin.Show())
                    Me.Invoke(Sub() setConnectState(0))
                    username = ""
                    password = ""
                    Exit Sub
                End If
            Catch ex As Exception

            End Try

            ' Hentikan Loop Jika Tombol Stop Ditekan
            If iConnect.Caption = "Connect" Then Exit Do

            LoginMonitor.Wait(1000)
        Loop While 1
    End Sub

    Private Sub doMonitor()
        Try
            Do
                If tsConnMonitor.Token.IsCancellationRequested Then Exit Do
                If ConsoleSocket Is Nothing Then Exit Do
                If ConsoleSocket.isConnected = False Then Exit Do
                ConnMonitor.Wait(1000)
            Loop While 1
        Catch ex As Exception
            Console.WriteLine("Connection Monitoring Closed")
        End Try

        If iConnect.Caption = "Disconnect" Then
            Me.Invoke(Sub() enableDisableControl(0, 1))
            '------------------------------
            Try
                If tsConnMonitor.Token.IsCancellationRequested = False Then tsConnMonitor.Cancel()
                If tsSyncTask.Token.IsCancellationRequested = False Then tsSyncTask.Cancel()
                If tsWaitTask.Token.IsCancellationRequested = False Then tsWaitTask.Cancel()

                ConsoleSocket.Stream.Close()
                ConsoleSocket.Sock.Close()
            Catch ex As Exception

            End Try
            ConsoleSocket = Nothing
            SockGlobal = ConsoleSocket
            '------------------------------
            Try
                Me.Invoke(Sub() frmLoginMain.setNotifyBaloon("Synchronization Client", "Disconnected From Server" + vbCrLf + "Trying to ReConnect ...", ToolTipIcon.Warning))
            Catch ex As Exception

            End Try
            Me.Invoke(Sub() setConnectState(4))
            Me.Invoke(Sub() doLogin(username, password))
        Else
            If iConnect.Caption = "Disconnect" Then Me.Invoke(Sub() iConnect.PerformClick())
        End If

    End Sub

    Public Sub SyncResetStat(ByVal id As Long)
        Dim mquery As New cMySQLDatabase
        If mquery.mysql_non_query("UPDATE tb_syncconfig_link SET synchronized='0' WHERE id='" & id & "'") Then
            Console.WriteLine("Sync Resetted")
        End If
    End Sub

    Public Sub doWaitSyncResponse()
        Do
            Try
                ' If Cancellation Token is Set Then Stop Task
                If tsWaitTask.Token.IsCancellationRequested = True Then
                    Console.WriteLine("Synchronization Waiting Task was cancelled")
                    Exit Do
                End If

                ' If Disconnect Then Stop Task
                If iConnect.Caption = "Connect" Or ConsoleSocket Is Nothing Then Exit Do

                If WaitTaskResponse Then
                    Select Case WaitTaskResponseHandler
                        Case 0
                            'Sync Success
                            Console.WriteLine("Sync Complete")
                        Case 1
                            Console.WriteLine("Sync Failed! Unknown Contact")
                        Case 2
                            Console.WriteLine("Sync Failed! Contact is Offline")
                        Case 3
                            Console.WriteLine("Sync Failed! Reason: Unknown Response")
                        Case Else
                            Console.WriteLine("Sync Failed! Reason: Server can't identify the request")
                    End Select
                    Exit Do
                End If
                SyncResponseTask.Wait(500)
            Catch ex As Exception

            End Try
            
        Loop While 1
    End Sub

    Public Sub doSyncTask()
        Dim mquery As cMySQLDatabase
        Dim obj As Object
        Dim tb_1 As DataTable
        Dim tb_2 As DataTable
        Dim str As String
        Console.WriteLine("Synchronization Task Started")
        Do
            Try
                ' If Cancellation Token is Set Then Stop Task
                If tsSyncTask.Token.IsCancellationRequested = True Then
                    Console.WriteLine("Synchronization Task was cancelled")
                    Exit Do
                End If

                ' If Disconnect Then Stop Task
                If iConnect.Caption = "Connect" Or ConsoleSocket Is Nothing Then Exit Do

                mquery = New cMySQLDatabase
                'Synchronization Task Modul by Server
                obj = mquery.mysql_query("SELECT a.id,a.id_syncconfig,a.last_timestamp,a.last_executionid,a.synchronized,b.id AS 'master_id',b.database AS 'db',c.email,d.* FROM tb_syncconfig_link AS a " & _
                                    "INNER JOIN tb_syncconfig AS b ON a.id_syncconfig=b.id " & _
                                    "INNER JOIN tb_contact AS c ON c.id_kontak=a.id_kontak " & _
                                    "INNER JOIN tb_host AS d on d.id_host=b.id_host WHERE a.synchronized='0'")
                If Type.GetTypeCode(obj.GetType) <> TypeCode.Boolean Then
                    tb_1 = obj
                    For i As Integer = 0 To tb_1.Rows.Count - 1
                        str = ""
                        mquery.setConnection(False, tb_1.Rows(i)("host"), tb_1.Rows(i)("port"), tb_1.Rows(i)("username"), tb_1.Rows(i)("password"), tb_1.Rows(i)("db"))
                        obj = mquery.mysql_query("SELECT * FROM " & tb_1.Rows(i)("db") & ".auditlog_" & tb_1.Rows(i)("db") & " WHERE `execution_id`>" & tb_1.Rows(i)("last_executionid").ToString & " AND `timestamp`>='" & MinDate(tb_1.Rows(i)("last_timestamp").ToString) & "' ORDER BY timestamp ASC")
                        If Type.GetTypeCode(obj.GetType) <> TypeCode.Boolean Then
                            tb_2 = obj
                            If tb_2.Rows.Count > 0 Then
                                mquery.setConnection(True)
                                If mquery.mysql_non_query("UPDATE tb_syncconfig_link SET synchronized='1' WHERE id='" & tb_1.Rows(i)("id") & "'") Then
                                    'Data Format
                                    'id_link*master_id*database*table_name~timestamp~exec_id~action(I,U,D)~PK~field~data#table_name~timestamp~exec_id~action(I,U,D)~PK~field~data
                                    str = str & tb_1.Rows(i)("id") & "*" & tb_1.Rows(i)("master_id") & "*" & tb_1.Rows(i)("db") & "*"
                                    For j As Integer = 0 To tb_2.Rows.Count - 1
                                        str = str & tb_2.Rows(j)("table_name") & "~" & MinDate(tb_2.Rows(j)("timestamp").ToString) & "~" & tb_2.Rows(j)("execution_id").ToString & "~" & tb_2.Rows(j)("action") & "~" & tb_2.Rows(j)("field_pk") & "~" & tb_2.Rows(j)("field") & "~" & tb_2.Rows(j)("old_data") & "~" & tb_2.Rows(j)("new_data")
                                        If j < tb_2.Rows.Count - 1 Then
                                            str = str & "#"
                                        End If
                                    Next
                                    'Send to Slave
                                    Try
                                        ConsoleSocket.sendMessages(String.Format("/callback{0}/dbsyncdo{0}{1}", Packet.pSplit, str), tb_1.Rows(i)("email"))
                                    Catch ex As Exception
                                        mquery.mysql_non_query(String.Format("INSERT INTO tb_msg_outbox(message,user_target,status) VALUES('/callback{0}/dbsyncdo{0}{1}','{2}','0')", Packet.pSplit, str, tb_1.Rows(i)("email")))
                                    End Try

                                    SyncTask.Wait(500)
                                End If
                            End If
                        End If
                    Next

                End If
                SyncTask.Wait(500)
            Catch ex As Exception

            End Try

        Loop While 1
    End Sub

    Private Sub ConsoleSocket_onDisconnected() Handles ConsoleSocket.onDisconnected
        Me.Invoke(Sub() setConnectState(0))
    End Sub

    ' Prosedur ini akan berjalan Jika Ada Data  Diterima Oleh Socket
    Private Sub ConsoleSocket_dataResponse(response() As String) Handles ConsoleSocket.dataResponse
        
        If response.Length > 1 Then
            Select Case response(0)
                Case "1"
                    'Waiting doLogin to Complete its Task
                    tsLoginMonitor.Cancel()
                    If LoginMonitor.Status = TaskStatus.Running Then LoginMonitor.Wait()
                    '------------------------------------
                    Select Case response(1)
                        Case "0"
                            SockGlobal = ConsoleSocket
                            nickname = response(3)
                            Me.Invoke(Sub() setConnectState(3))
                            Me.Invoke(Sub() enableDisableControl(0, 0))
                            Me.Invoke(Sub() resetCancellationToken())
                            tsConnMonitor = New CancellationTokenSource
                            ConnMonitor = Task.Factory.StartNew(AddressOf doMonitor, tsConnMonitor.Token)
                            SyncTask = Task.Factory.StartNew(AddressOf doSyncTask, tsSyncTask.Token)
                        Case "2"
                            Me.Invoke(New Action(Of String)(AddressOf Console_Append), "Login Failed: " & getResponseMsg(response(0), "", response(1)))
                            Me.Invoke(Sub() frmLogin.Show())
                            Me.Invoke(Sub() setConnectState(0))
                        Case "9"
                            Me.Invoke(New Action(Of String)(AddressOf Console_Append), "Login Failed: " & getResponseMsg(response(0), "", response(1)))
                            Me.Invoke(Sub() frmLogin.Show())
                            Me.Invoke(Sub() setConnectState(0))
                            username = ""
                            password = ""
                        Case Else
                            Me.Invoke(New Action(Of String)(AddressOf Console_Append), "Login Failed: " & getResponseMsg(response(0), "", response(1)))
                            Me.Invoke(Sub() setConnectState(0))
                    End Select
                Case "10"
                    ''Prevent Message out From Here
                Case "100" 'Messages Received
                    'Response Index
                    '0=Response Code
                    '1=Sender
                    '2=Message/Message Code
                    '3=Detail From Message Code
                    Select Case response(2)
                        Case "/dbsyncregister"
                            SyncRegister(response, ConsoleSocket)
                        Case "/dbsyncregisterresponse"
                            'Prevent Message out From Here
                            'Output to frmSynchronization_Form.vb
                        Case "/dbsyncgetconfig"
                            SyncGetConfig(response, ConsoleSocket)
                        Case "/dbsyncconfigresponse" 'Slave Action
                            'Prevent dbsyncresponse Message out From Here
                            'Output to frmSynchronization_Form.vb
                        Case "/dbsyncdo" 'Slave Action
                            'Cancel SyncTask
                            Me.Invoke(Sub() tsSyncTask.Cancel())

                            'Wait SyncTask To Cancel
                            If SyncTask.Status = TaskStatus.Running Then
                                Me.Invoke(Sub() SyncTask.Wait())
                            End If

                            'Do Synchronization
                            SyncDo(response, ConsoleSocket)

                            'Restart Sync Task
                            Me.Invoke(Sub() tsSyncTask = New CancellationTokenSource)
                            Me.Invoke(Sub() SyncTask = Task.Factory.StartNew(AddressOf doSyncTask, tsSyncTask.Token))
                        Case "/dbsyncdoresponse" 'Master Action
                            'Receive Sync Status From Slave
                            'Modify SyncResponse State
                            Me.Invoke(Sub() WaitTaskResponse = True)
                            Me.Invoke(Sub() WaitTaskResponseHandler = 0)

                            'Processing The Response
                            Try
                                If SyncResponseTask.Status = TaskStatus.Running Then
                                    Me.Invoke(Sub() SyncResponseTask.Wait())
                                End If
                            Catch ex As Exception

                            End Try
                            
                            SyncDoResponse(response, ConsoleSocket)
                            '----------------------------------------------------

                            'Reset SyncResponse
                            Me.Invoke(Sub() WaitTaskResponse = False)
                            Me.Invoke(Sub() WaitTaskResponseHandler = 0)
                            Me.Invoke(Sub() tsWaitTask = New CancellationTokenSource)
                            Me.Invoke(Sub() SyncResponseTask = Task.Factory.StartNew(AddressOf doWaitSyncResponse, tsWaitTask.Token))

                        Case "/responseunknowncontact" 'Master Action
                            'Unknown Contact Response From Server
                            'For Synchronization
                            Me.Invoke(Sub() WaitTaskResponse = True)
                            Me.Invoke(Sub() WaitTaskResponseHandler = 1)

                            Try
                                If SyncResponseTask.Status = TaskStatus.Running Then
                                    Me.Invoke(Sub() SyncResponseTask.Wait())
                                End If
                            Catch ex As Exception

                            End Try
                            
                            If response.Length > 4 Then
                                Select Case response(3).ToString
                                    Case "/dbsyncdo"
                                        Me.Invoke(Sub() SyncResetStat(response(4).Split("*")(0)))
                                End Select
                            End If
                            Me.Invoke(Sub() WaitTaskResponse = False)
                            Me.Invoke(Sub() WaitTaskResponseHandler = 0)
                            Me.Invoke(Sub() tsWaitTask = New CancellationTokenSource)
                            Me.Invoke(Sub() SyncResponseTask = Task.Factory.StartNew(AddressOf doWaitSyncResponse, tsWaitTask.Token))
                            '----- End Synchronization Task
                        Case "/responseofflinecontact" 'Master Action
                            'Offline Contact Response From Server

                            'For Synchronization
                            Me.Invoke(Sub() WaitTaskResponse = True)
                            Me.Invoke(Sub() WaitTaskResponseHandler = 2)
                            Try
                                If SyncResponseTask.Status = TaskStatus.Running Then
                                    Me.Invoke(Sub() SyncResponseTask.Wait())
                                End If
                            Catch ex As Exception

                            End Try
                            
                            Me.Invoke(Sub() WaitTaskResponse = False)
                            Me.Invoke(Sub() WaitTaskResponseHandler = 0)
                            Me.Invoke(Sub() tsWaitTask = New CancellationTokenSource)
                            Me.Invoke(Sub() SyncResponseTask = Task.Factory.StartNew(AddressOf doWaitSyncResponse, tsWaitTask.Token))

                            '----- End Synchronization Task
                        Case Else
                            'Normal Messages
                            Me.Invoke(Sub() Console_Append(response(2)))
                    End Select

                    'If response(2).ToString.IndexOf(get_separator().ToString) > -1 Then

                    'End If
            End Select
        End If
    End Sub

    Private Sub enableDisableControl(Optional ByVal group As Integer = -1, Optional ByVal code As Integer = -1)
        If group > -1 Then
            Select Case group
                Case 0 ' For Login
                    Select Case code
                        Case 0 'Login Complete
                            BarButtonItemProfile.Enabled = True
                            BarButtonItemProfile.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
                            iMessage.Enabled = True
                        Case 1 'Login Failed
                            BarButtonItemProfile.Enabled = False
                            BarButtonItemProfile.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
                            iMessage.Enabled = False
                    End Select
            End Select
        End If
    End Sub

    Private Sub resetCancellationToken()
        tsSyncTask = New CancellationTokenSource
        tsWaitTask = New CancellationTokenSource
    End Sub

    Private Sub iConnect_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles iConnect.ItemClick
        If iConnect.Caption = "Connect" Then
            frmLogin.Show()
        Else
            Me.Invoke(Sub() enableDisableControl(0, 1))
            Me.Invoke(Sub() setConnectState(0))
            Try
                If ConsoleSocket.Client.Connected Or ConsoleSocket.Client.Client.Connected Then
                    tsWaitTask.Cancel()
                    tsSyncTask.Cancel()
                    tsConnMonitor.Cancel()
                    tsLoginMonitor.Cancel()

                    ConsoleSocket.Stream.Close()
                    ConsoleSocket.Sock.Close()
                    ConsoleSocket = Nothing
                    SockGlobal = ConsoleSocket
                End If
            Catch ex As Exception

            End Try
            
        End If
    End Sub

    Private Sub BarButtonItemProfile_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItemProfile.ItemClick
        frmProfile.ShowDialog()
    End Sub

    Private Sub iOperationDB_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles iOperationDB.ItemClick
        frmOperationServer.ShowDialog()
    End Sub

    Private Sub iKeyword_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles iKeyword.ItemClick
        frmOperation.ShowDialog()
    End Sub

    Private Sub iContact_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles iContact.ItemClick
        frmContact.ShowDialog()
    End Sub

    Private Sub iManageUser_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles iManageUser.ItemClick
        frmManageUser.Dispose()
        frmManageUser.ShowDialog()
    End Sub

    Private Sub iUserManage_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles iUserManage.ItemClick
        frmSingleUserProfile.Dispose()
        frmSingleUserProfile.ShowDialog()
    End Sub

    Private Sub iGroup_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles iGroup.ItemClick
        frmGroup.ShowDialog()
    End Sub

    Private Sub iSynchronization_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles iSynchronization.ItemClick
        frmSynchronization.Dispose()
        frmSynchronization.ShowDialog()
    End Sub

    Private Sub ToolStripMenuItemClearConsole_Click(sender As Object, e As EventArgs) Handles ToolStripMenuItemClearConsole.Click
        txtConsole.Text = "> "
        txtConsole.Select(txtConsole.TextLength, 0)
    End Sub

    Private Sub txtConsole_MouseDown(sender As Object, e As MouseEventArgs) Handles txtConsole.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Right Then
            ContextMenuRightConsole.Show(txtConsole, New Point(e.X, e.Y))
        End If
    End Sub

    Private Sub iApAbout_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles iApAbout.ItemClick
        Dim str_about() As Byte = New Byte() {65, 0, 112, 0, 108, 0, 105, 0, 107, 0, 97, 0, 115, _
                                              0, 105, 0, 32, 0, 67, 0, 108, 0, 105, 0, 101, 0, 110, _
                                              0, 116, 0, 32, 0, 77, 0, 111, 0, 77, 0, 32, 0, 83, 0, _
                                              105, 0, 110, 0, 107, 0, 114, 0, 111, 0, 110, 0, 105, 0, _
                                              115, 0, 97, 0, 115, 0, 105, 0, 32, 0, 68, 0, 97, 0, 116, _
                                              0, 97, 0, 98, 0, 97, 0, 115, 0, 101, 0, 32, 0, 118, 0, 49, _
                                              0, 46, 0, 48, 0, 13, 0, 10, 0, 13, 0, 10, 0, 67, 0, 114, 0, _
                                              101, 0, 97, 0, 116, 0, 101, 0, 100, 0, 32, 0, 66, 0, 121, 0, _
                                              58, 0, 32, 0, 13, 0, 10, 0, 82, 0, 97, 0, 105, 0, 32, 0, 71, _
                                              0, 117, 0, 100, 0, 97, 0, 107, 0, 101, 0, 115, 0, 97, 0, 32, _
                                              0, 9, 0, 40, 0, 49, 0, 48, 0, 48, 0, 52, 0, 53, 0, 48, 0, 53, _
                                              0, 48, 0, 48, 0, 53, 0, 41, 0, 13, 0, 10, 0, 71, 0, 101, 0, _
                                              100, 0, 101, 0, 32, 0, 72, 0, 97, 0, 100, 0, 105, 0, 32, 0, _
                                              83, 0, 117, 0, 114, 0, 121, 0, 97, 0, 32, 0, 9, 0, 40, 0, _
                                              49, 0, 48, 0, 48, 0, 52, 0, 53, 0, 48, 0, 53, 0, 48, 0, 48, _
                                              0, 51, 0, 41, 0, 13, 0, 10, 0, 13, 0, 10, 0, 169, 0, 50, 0, _
                                              48, 0, 49, 0, 52, 0, 32, 0, 84, 0, 101, 0, 107, 0, 110, 0, 111, _
                                              0, 108, 0, 111, 0, 103, 0, 105, 0, 32, 0, 73, 0, 110, 0, 102, 0, _
                                              111, 0, 114, 0, 109, 0, 97, 0, 115, 0, 105, 0, 44, 0, 32, 0, 70, _
                                              0, 97, 0, 107, 0, 117, 0, 108, 0, 116, 0, 97, 0, 115, 0, 32, 0, _
                                              84, 0, 101, 0, 107, 0, 110, 0, 105, 0, 107, 0, 44, 0, 32, 0, 85, _
                                              0, 110, 0, 105, 0, 118, 0, 101, 0, 114, 0, 115, 0, 105, 0, 116, 0, _
                                              97, 0, 115, 0, 32, 0, 85, 0, 100, 0, 97, 0, 121, 0, 97, 0, 110, 0, 97, 0}

        MessageBox.Show(System.Text.Encoding.Unicode.GetString(str_about), "About", MessageBoxButtons.OK, MessageBoxIcon.Information)
    End Sub

    

    Private Sub ribbonControl1_Click(sender As Object, e As EventArgs) Handles ribbonControl1.Click

    End Sub
End Class